// 天干
const HEAVENLY_STEMS = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸']
// 地支
const EARTHLY_BRANCHES = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥']
// 五行
const FIVE_ELEMENTS = ['金', '木', '水', '火', '土']
// 纳音五行
const NAYIN = {
  '甲子': '海中金', '乙丑': '海中金',
  '丙寅': '炉中火', '丁卯': '炉中火',
  '戊辰': '大林木', '己巳': '大林木',
  '庚午': '路旁土', '辛未': '路旁土',
  '壬申': '剑锋金', '癸酉': '剑锋金',
  '甲戌': '山头火', '乙亥': '山头火',
  '丙子': '涧下水', '丁丑': '涧下水',
  '戊寅': '城头土', '己卯': '城头土',
  '庚辰': '白蜡金', '辛巳': '白蜡金',
  '壬午': '杨柳木', '癸未': '杨柳木',
  '甲申': '泉中水', '乙酉': '泉中水',
  '丙戌': '屋上土', '丁亥': '屋上土',
  '戊子': '霹雳火', '己丑': '霹雳火',
  '庚寅': '松柏木', '辛卯': '松柏木',
  '壬辰': '长流水', '癸巳': '长流水',
  '甲午': '沙中金', '乙未': '沙中金',
  '丙申': '山下火', '丁酉': '山下火',
  '戊戌': '平地木', '己亥': '平地木',
  '庚子': '壁上土', '辛丑': '壁上土',
  '壬寅': '金箔金', '癸卯': '金箔金',
  '甲辰': '覆灯火', '乙巳': '覆灯火',
  '丙午': '天河水', '丁未': '天河水',
  '戊申': '大驿土', '己酉': '大驿土',
  '庚戌': '钗钏金', '辛亥': '钗钏金',
  '壬子': '桑柘木', '癸丑': '桑柘木',
  '甲寅': '大溪水', '乙卯': '大溪水',
  '丙辰': '沙中土', '丁巳': '沙中土',
  '戊午': '天上火', '己未': '天上火',
  '庚申': '石榴木', '辛酉': '石榴木',
  '壬戌': '大海水', '癸亥': '大海水'
}

// 时辰对应地支
const TIME_TO_BRANCH = {
  '23,0': '子', '1,2': '丑', '3,4': '寅', '5,6': '卯',
  '7,8': '辰', '9,10': '巳', '11,12': '午', '13,14': '未',
  '15,16': '申', '17,18': '酉', '19,20': '戌', '21,22': '亥'
}

// 天干五行
const STEM_TO_ELEMENT = {
  '甲': '木', '乙': '木',
  '丙': '火', '丁': '火',
  '戊': '土', '己': '土',
  '庚': '金', '辛': '金',
  '壬': '水', '癸': '水'
}

// 地支五行
const BRANCH_TO_ELEMENT = {
  '子': '水', '丑': '土', '寅': '木', '卯': '木',
  '辰': '土', '巳': '火', '午': '火', '未': '土',
  '申': '金', '酉': '金', '戌': '土', '亥': '水'
}

// 地支藏干
const BRANCH_HIDDEN_STEMS = {
  '子': ['癸'],
  '丑': ['己', '癸', '辛'],
  '寅': ['甲', '丙', '戊'],
  '卯': ['乙'],
  '辰': ['戊', '乙', '癸'],
  '巳': ['丙', '戊', '庚'],
  '午': ['丁', '己'],
  '未': ['己', '丁', '乙'],
  '申': ['庚', '壬', '戊'],
  '酉': ['辛'],
  '戌': ['戊', '辛', '丁'],
  '亥': ['壬', '甲']
}

class BaziCalculator {
  constructor() {
    this.lunar = require('./lunar')
  }

  // 计算八字
  calculateBazi(birthDate, birthTime, gender) {
    // 1. 将公历转换为农历
    const lunarDate = this.convertToLunar(birthDate)
    
    // 2. 计算年柱
    const yearPillar = this.calculateYearPillar(lunarDate.year)
    
    // 3. 计算月柱
    const monthPillar = this.calculateMonthPillar(yearPillar[0], lunarDate.month)
    
    // 4. 计算日柱
    const dayPillar = this.calculateDayPillar(birthDate)
    
    // 5. 计算时柱
    const hourPillar = this.calculateHourPillar(birthTime, dayPillar[0])
    
    // 6. 计算五行分布
    const wuxing = this.calculateWuxing(yearPillar, monthPillar, dayPillar, hourPillar)
    
    // 7. 计算大运
    const fortune = this.calculateFortune(yearPillar, monthPillar, dayPillar, hourPillar, gender)
    
    // 8. 计算喜用神
    const xiyong = this.calculateXiyong(yearPillar, monthPillar, dayPillar, hourPillar)
    
    // 9. 计算十神格局
    const shishen = this.calculateShishen(yearPillar, monthPillar, dayPillar, hourPillar)
    
    // 10. 计算命理解读
    const interpretation = this.calculateInterpretation(yearPillar, monthPillar, dayPillar, hourPillar, gender)
    
    return {
      yearPillar,
      monthPillar,
      dayPillar,
      hourPillar,
      heavenlyStems: yearPillar[0] + monthPillar[0] + dayPillar[0] + hourPillar[0],
      earthlyBranches: yearPillar[1] + monthPillar[1] + dayPillar[1] + hourPillar[1],
      hiddenStems: this.getHiddenStems(yearPillar[1], monthPillar[1], dayPillar[1], hourPillar[1]),
      nayin: this.getNayin(yearPillar, monthPillar, dayPillar, hourPillar),
      wuxing,
      fortune,
      xiyong,
      shishen,
      interpretation
    }
  }

  // 将公历转换为农历
  convertToLunar(date) {
    const [year, month, day] = date.split('-').map(Number)
    return this.lunar.solarToLunar(year, month, day)
  }

  // 计算年柱
  calculateYearPillar(lunarYear) {
    const stemIndex = (lunarYear - 4) % 10
    const branchIndex = (lunarYear - 4) % 12
    return [HEAVENLY_STEMS[stemIndex], EARTHLY_BRANCHES[branchIndex]]
  }

  // 计算月柱
  calculateMonthPillar(yearStem, lunarMonth) {
    // 根据年干确定月干起始
    const monthStemStart = {
      '甲': 0, '己': 0,  // 甲己丙佳
      '乙': 2, '庚': 2,  // 乙庚戊癸
      '丙': 4, '辛': 4,  // 丙辛庚乙
      '丁': 6, '壬': 6,  // 丁壬壬丁
      '戊': 8, '癸': 8   // 戊癸甲己
    }[yearStem]

    const stemIndex = (monthStemStart + lunarMonth - 1) % 10
    const branchIndex = (lunarMonth + 1) % 12
    
    return [HEAVENLY_STEMS[stemIndex], EARTHLY_BRANCHES[branchIndex]]
  }

  // 计算日柱
  calculateDayPillar(date) {
    const baseDate = new Date('1900-01-31')  // 甲子日
    const targetDate = new Date(date)
    const daysDiff = Math.floor((targetDate - baseDate) / (24 * 60 * 60 * 1000))
    
    const stemIndex = daysDiff % 10
    const branchIndex = daysDiff % 12
    
    return [HEAVENLY_STEMS[stemIndex], EARTHLY_BRANCHES[branchIndex]]
  }

  // 计算时柱
  calculateHourPillar(time, dayStem) {
    const hour = parseInt(time.split(':')[0])
    let branch = ''
    
    // 确定时辰地支
    for (const [range, value] of Object.entries(TIME_TO_BRANCH)) {
      const [start, end] = range.split(',').map(Number)
      if ((hour >= start && hour <= end) || (start === 23 && hour >= 23) || (start === 23 && hour === 0)) {
        branch = value
        break
      }
    }

    // 根据日干确定时干起始
    const stemStart = {
      '甲': 0, '己': 0,
      '乙': 2, '庚': 2,
      '丙': 4, '辛': 4,
      '丁': 6, '壬': 6,
      '戊': 8, '癸': 8
    }[dayStem]

    // 计算时干
    const branchIndex = EARTHLY_BRANCHES.indexOf(branch)
    const stemIndex = (stemStart + branchIndex) % 10
    
    return [HEAVENLY_STEMS[stemIndex], branch]
  }

  // 计算五行分布
  calculateWuxing(yearPillar, monthPillar, dayPillar, hourPillar) {
    const elements = { '金': 0, '木': 0, '水': 0, '火': 0, '土': 0 }
    
    // 计算天干五行
    const stems = [yearPillar[0], monthPillar[0], dayPillar[0], hourPillar[0]]
    stems.forEach(stem => {
      elements[STEM_TO_ELEMENT[stem]] += 1.2  // 天干权重1.2
    })

    // 计算地支五行
    const branches = [yearPillar[1], monthPillar[1], dayPillar[1], hourPillar[1]]
    branches.forEach(branch => {
      elements[BRANCH_TO_ELEMENT[branch]] += 1  // 地支权重1
    })

    // 计算藏干五行
    branches.forEach(branch => {
      BRANCH_HIDDEN_STEMS[branch].forEach(stem => {
        elements[STEM_TO_ELEMENT[stem]] += 0.8  // 藏干权重0.8
      })
    })

    // 计算总分
    const total = Object.values(elements).reduce((a, b) => a + b, 0)

    // 转换为百分比
    return Object.entries(elements).map(([element, value]) => ({
      element,
      percentage: Math.round((value / total) * 100)
    }))
  }

  // 获取藏干
  getHiddenStems(yearBranch, monthBranch, dayBranch, hourBranch) {
    const allHiddenStems = []
    ;[yearBranch, monthBranch, dayBranch, hourBranch].forEach(branch => {
      allHiddenStems.push(...BRANCH_HIDDEN_STEMS[branch])
    })
    return [...new Set(allHiddenStems)].join('')
  }

  // 获取纳音
  getNayin(yearPillar, monthPillar, dayPillar, hourPillar) {
    return {
      year: NAYIN[yearPillar.join('')],
      month: NAYIN[monthPillar.join('')],
      day: NAYIN[dayPillar.join('')],
      hour: NAYIN[hourPillar.join('')]
    }
  }

  // 计算大运
  calculateFortune(yearPillar, monthPillar, dayPillar, hourPillar, gender) {
    const startAge = gender === '男' ? 1 : 2
    const direction = gender === '男' ? 1 : -1
    const fortune = []
    
    let currentStem = HEAVENLY_STEMS.indexOf(monthPillar[0])
    let currentBranch = EARTHLY_BRANCHES.indexOf(monthPillar[1])
    
    for (let i = 0; i < 8; i++) {
      currentStem = (currentStem + direction + 10) % 10
      currentBranch = (currentBranch + direction + 12) % 12
      
      fortune.push({
        age: startAge + i * 10,
        year: (new Date().getFullYear() + i * 10).toString(),
        pillar: HEAVENLY_STEMS[currentStem] + EARTHLY_BRANCHES[currentBranch]
      })
    }
    
    return fortune
  }

  // 计算喜用神
  calculateXiyong(yearPillar, monthPillar, dayPillar, hourPillar) {
    const wuxing = this.calculateWuxing(yearPillar, monthPillar, dayPillar, hourPillar)
    const dayStem = dayPillar[0]
    const dayElement = STEM_TO_ELEMENT[dayStem]
    
    // 计算五行强弱
    const elementStrength = {}
    wuxing.forEach(item => {
      elementStrength[item.element] = item.percentage
    })
    
    // 根据日主五行确定喜用神
    let favorable = []
    let unfavorable = []
    let advice = ''
    
    switch(dayElement) {
      case '木':
        if (elementStrength['木'] < 20) {
          favorable.push({ element: '木', reason: '日主木弱，喜木生扶' })
        }
        if (elementStrength['水'] < 15) {
          favorable.push({ element: '水', reason: '日主木弱，喜水生木' })
        }
        if (elementStrength['金'] > 25) {
          unfavorable.push({ element: '金', reason: '金旺克木，不利日主' })
        }
        advice = '宜佩戴绿色、青色饰品，居住环境宜有树木'
        break
      case '火':
        if (elementStrength['火'] < 20) {
          favorable.push({ element: '火', reason: '日主火弱，喜火生扶' })
        }
        if (elementStrength['木'] < 15) {
          favorable.push({ element: '木', reason: '日主火弱，喜木生火' })
        }
        if (elementStrength['水'] > 25) {
          unfavorable.push({ element: '水', reason: '水旺克火，不利日主' })
        }
        advice = '宜佩戴红色、紫色饰品，居住环境宜向阳'
        break
      case '土':
        if (elementStrength['土'] < 20) {
          favorable.push({ element: '土', reason: '日主土弱，喜土生扶' })
        }
        if (elementStrength['火'] < 15) {
          favorable.push({ element: '火', reason: '日主土弱，喜火生土' })
        }
        if (elementStrength['木'] > 25) {
          unfavorable.push({ element: '木', reason: '木旺克土，不利日主' })
        }
        advice = '宜佩戴黄色、棕色饰品，居住环境宜平稳'
        break
      case '金':
        if (elementStrength['金'] < 20) {
          favorable.push({ element: '金', reason: '日主金弱，喜金生扶' })
        }
        if (elementStrength['土'] < 15) {
          favorable.push({ element: '土', reason: '日主金弱，喜土生金' })
        }
        if (elementStrength['火'] > 25) {
          unfavorable.push({ element: '火', reason: '火旺克金，不利日主' })
        }
        advice = '宜佩戴白色、金色饰品，居住环境宜干燥'
        break
      case '水':
        if (elementStrength['水'] < 20) {
          favorable.push({ element: '水', reason: '日主水弱，喜水生扶' })
        }
        if (elementStrength['金'] < 15) {
          favorable.push({ element: '金', reason: '日主水弱，喜金生水' })
        }
        if (elementStrength['土'] > 25) {
          unfavorable.push({ element: '土', reason: '土旺克水，不利日主' })
        }
        advice = '宜佩戴黑色、蓝色饰品，居住环境宜近水'
        break
    }
    
    return {
      favorable,
      unfavorable,
      advice
    }
  }

  // 计算十神格局
  calculateShishen(yearPillar, monthPillar, dayPillar, hourPillar) {
    const dayStem = dayPillar[0]
    const dayElement = STEM_TO_ELEMENT[dayStem]
    
    // 十神对应关系
    const shishenMap = {
      '木': {
        '木': { name: '比肩', value: '同我', meaning: '代表兄弟姐妹、同辈、竞争' },
        '火': { name: '食神', value: '生我', meaning: '代表子女、晚辈、下属' },
        '土': { name: '财', value: '我生', meaning: '代表财富、妻子、父亲' },
        '金': { name: '官', value: '克我', meaning: '代表权力、丈夫、上司' },
        '水': { name: '印', value: '生我', meaning: '代表母亲、长辈、贵人' }
      },
      '火': {
        '木': { name: '印', value: '生我', meaning: '代表母亲、长辈、贵人' },
        '火': { name: '比肩', value: '同我', meaning: '代表兄弟姐妹、同辈、竞争' },
        '土': { name: '食神', value: '生我', meaning: '代表子女、晚辈、下属' },
        '金': { name: '财', value: '我生', meaning: '代表财富、妻子、父亲' },
        '水': { name: '官', value: '克我', meaning: '代表权力、丈夫、上司' }
      },
      '土': {
        '木': { name: '官', value: '克我', meaning: '代表权力、丈夫、上司' },
        '火': { name: '印', value: '生我', meaning: '代表母亲、长辈、贵人' },
        '土': { name: '比肩', value: '同我', meaning: '代表兄弟姐妹、同辈、竞争' },
        '金': { name: '食神', value: '生我', meaning: '代表子女、晚辈、下属' },
        '水': { name: '财', value: '我生', meaning: '代表财富、妻子、父亲' }
      },
      '金': {
        '木': { name: '财', value: '我生', meaning: '代表财富、妻子、父亲' },
        '火': { name: '官', value: '克我', meaning: '代表权力、丈夫、上司' },
        '土': { name: '印', value: '生我', meaning: '代表母亲、长辈、贵人' },
        '金': { name: '比肩', value: '同我', meaning: '代表兄弟姐妹、同辈、竞争' },
        '水': { name: '食神', value: '生我', meaning: '代表子女、晚辈、下属' }
      },
      '水': {
        '木': { name: '食神', value: '生我', meaning: '代表子女、晚辈、下属' },
        '火': { name: '财', value: '我生', meaning: '代表财富、妻子、父亲' },
        '土': { name: '官', value: '克我', meaning: '代表权力、丈夫、上司' },
        '金': { name: '印', value: '生我', meaning: '代表母亲、长辈、贵人' },
        '水': { name: '比肩', value: '同我', meaning: '代表兄弟姐妹、同辈、竞争' }
      }
    }
    
    // 计算各柱十神
    const pillars = [yearPillar, monthPillar, dayPillar, hourPillar]
    const details = []
    
    pillars.forEach((pillar, index) => {
      const stemElement = STEM_TO_ELEMENT[pillar[0]]
      const branchElement = BRANCH_TO_ELEMENT[pillar[1]]
      
      details.push({
        name: shishenMap[dayElement][stemElement].name,
        value: shishenMap[dayElement][stemElement].value,
        meaning: shishenMap[dayElement][stemElement].meaning
      })
      
      details.push({
        name: shishenMap[dayElement][branchElement].name,
        value: shishenMap[dayElement][branchElement].value,
        meaning: shishenMap[dayElement][branchElement].meaning
      })
    })
    
    // 统计十神出现次数
    const shishenCount = {}
    details.forEach(item => {
      shishenCount[item.name] = (shishenCount[item.name] || 0) + 1
    })
    
    // 确定格局
    let pattern = '普通格局'
    let description = '五行较为均衡，无明显偏颇'
    
    if (shishenCount['比肩'] >= 3) {
      pattern = '比肩格'
      description = '比肩旺盛，主竞争、独立、自我'
    } else if (shishenCount['食神'] >= 3) {
      pattern = '食神格'
      description = '食神旺盛，主聪明、才艺、子女'
    } else if (shishenCount['财'] >= 3) {
      pattern = '财格'
      description = '财星旺盛，主富贵、财运、人缘'
    } else if (shishenCount['官'] >= 3) {
      pattern = '官格'
      description = '官星旺盛，主权力、地位、事业'
    } else if (shishenCount['印'] >= 3) {
      pattern = '印格'
      description = '印星旺盛，主学业、智慧、贵人'
    }
    
    return {
      pattern,
      description,
      details
    }
  }

  // 计算命理解读
  calculateInterpretation(yearPillar, monthPillar, dayPillar, hourPillar, gender) {
    const dayStem = dayPillar[0]
    const dayElement = STEM_TO_ELEMENT[dayStem]
    const wuxing = this.calculateWuxing(yearPillar, monthPillar, dayPillar, hourPillar)
    const shishen = this.calculateShishen(yearPillar, monthPillar, dayPillar, hourPillar)
    
    // 计算五行强弱
    const elementStrength = {}
    wuxing.forEach(item => {
      elementStrength[item.element] = item.percentage
    })
    
    // 根据日主五行和十神格局生成解读
    let personality = ''
    let career = ''
    let relationship = ''
    let health = ''
    
    // 性格特点解读
    switch(dayElement) {
      case '木':
        personality = '性格坚韧，有进取心，做事有条理，但有时过于固执。'
        break
      case '火':
        personality = '性格开朗，热情大方，富有创造力，但易冲动。'
        break
      case '土':
        personality = '性格稳重，重情重义，做事踏实，但有时过于保守。'
        break
      case '金':
        personality = '性格果断，重原则，做事严谨，但有时过于刚强。'
        break
      case '水':
        personality = '性格灵活，思维敏捷，适应力强，但有时过于善变。'
        break
    }
    
    // 事业发展解读
    if (shishen.pattern === '官格') {
      career = '适合从事管理、行政、公务员等工作，有领导才能。'
    } else if (shishen.pattern === '财格') {
      career = '适合从事金融、投资、经商等工作，财运较好。'
    } else if (shishen.pattern === '印格') {
      career = '适合从事教育、研究、文化等工作，学术成就较高。'
    } else if (shishen.pattern === '食神格') {
      career = '适合从事创意、艺术、餐饮等工作，才艺出众。'
    } else {
      career = '事业发展较为平稳，建议选择与自身五行相生的工作。'
    }
    
    // 感情姻缘解读
    if (gender === '男') {
      if (elementStrength['金'] > 25) {
        relationship = '感情较为专一，但易与伴侣产生分歧，建议多包容。'
      } else if (elementStrength['木'] > 25) {
        relationship = '感情生活丰富多彩，但易有桃花，需谨慎处理。'
      } else {
        relationship = '感情生活平稳，与伴侣相处融洽，婚姻较为美满。'
      }
    } else {
      if (elementStrength['水'] > 25) {
        relationship = '感情细腻，重视家庭，但易受情绪影响。'
      } else if (elementStrength['火'] > 25) {
        relationship = '感情热烈，追求浪漫，但易冲动，需理性对待。'
      } else {
        relationship = '感情生活和谐，与伴侣相互理解，家庭幸福。'
      }
    }
    
    // 健康建议解读
    switch(dayElement) {
      case '木':
        health = '注意肝胆系统，保持情绪稳定，适当运动。'
        break
      case '火':
        health = '注意心脑血管，避免过度劳累，保持充足睡眠。'
        break
      case '土':
        health = '注意消化系统，饮食规律，避免暴饮暴食。'
        break
      case '金':
        health = '注意呼吸系统，保持室内通风，避免受凉。'
        break
      case '水':
        health = '注意泌尿系统，保持水分充足，避免久坐。'
        break
    }
    
    return {
      personality,
      career,
      relationship,
      health
    }
  }
}

module.exports = BaziCalculator; 